Editor.Util = {
	isDragging: function () {
		return Editor.STATE.DRAGGER != undefined && Editor.STATE.DRAGGER.isActive();
	},
	undo: function () {
		Editor.Util.unselectAll();
		Editor.STATE.CMDSTACK.undo()
	},
	redo: function () {
		Editor.Util.unselectAll();
		Editor.STATE.CMDSTACK.redo()
	},
	prepareAddResource: function () {
		Editor.STATE.ADDSHAPE = Editor.Util.addResource;
		Editor.STATE.ADDDIALOG = 'dialogAddResource';
		Editor.Util.prepareAdd();
	},
	prepareAddLiteral: function () {
		Editor.STATE.ADDSHAPE = Editor.Util.addLiteral;
		Editor.STATE.ADDDIALOG = 'dialogAddLiteral';
		Editor.Util.prepareAdd();
	},
	prepareAdd: function () {
		$('#canvasAdd').addClass('canvas');
		$('#canvasAdd').css("width",""+Editor.CONFIG.CANVAS_WIDTH);
		$('#canvasAdd').css("height",""+Editor.CONFIG.CANVAS_HEIGHT);
		Editor.STATE.ISADDSHAPE = true;
	},
	addResource: function (x, y, u) {
		var n1 = new Editor.Namespace();
		n1.init();
		n1.setPrefix('');
		n1.setUri('');
		var r1 = new Editor.ResourceConnectable();
		r1.init(u);
		r1.setNamespace(n1);
		r1.setName('');
		r1.draw();
		r1.moveTo(x, y);
		Editor.STATE.SHAPES.store(r1.getUuid(),r1);
		return r1;
	},
	addProperty: function (x, y, u, rIni, rEnd) {
		var ns = new Editor.Namespace();
		ns.init();
		var prop = new Editor.Property();
		prop.init(u,rIni,rEnd);
		prop.setNamespace(ns);
		prop.setName('');
		prop.draw();
		prop.moveTo(x, y);
		Editor.STATE.SHAPES.store(prop.getUuid(),prop);
		return prop;
	},
	addLiteral: function (x, y, u) {
		var l1 = new Editor.Literal();
		l1.init(u);
		l1.setText('');
		l1.setLang('');
		l1.setDatatype('');
		l1.draw();
		l1.moveTo(x, y);
		Editor.STATE.SHAPES.store(l1.getUuid(),l1);
		return l1;
	},
	unselectAll: function () {
		var arrSelected = Editor.STATE.SELECTED;
		while (arrSelected.length>0) {
			var shape = arrSelected.pop();
			shape.unselect();
		}
	},
	select: function (shape) {
		Editor.STATE.SELECTED.push(shape);
		shape.select();
	},
	unselect: function (shape) {
		var arrSelected = Editor.STATE.SELECTED;
		var toRemove =-1;
		for(var i=0;i<arrSelected.length;i++) {
			if (shape.getUuid() == arrSelected[i].getUuid()) {
				toRemove = i;
			}
		}
		if(toRemove>=0) {
			arrSelected.splice(toRemove,1);
		}
	},
	toggleLang: function () {
		if (Editor.STATE.LANG.code == 'es') {
			Editor.STATE.LANG = Editor.LANG.EN;
		} else if (Editor.STATE.LANG.code == 'en') {
			Editor.STATE.LANG = Editor.LANG.ES;
		}
		Editor.Init.lang();
	},
	canvasAddClick: function (e) {
        var pos = $("#canvas").position();
		var x = e.clientX - pos.left;
		var y = e.clientY - pos.top;
		if (Editor.CONFIG.GRID_SNAP) {
			x = Math.round(x / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
			y = Math.round(y / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
		}
		var cmd = new JS.Command({
			execute: function () {
				if (this.shape != undefined) {
					this.shape.draw();
				} else {
					this.shape = Editor.STATE.ADDSHAPE(x, y);
					Editor.STATE.SHAPETOUPDATE = this.shape;
				}
			},
			undo: function () {
				this.shape._remove();
			},
			stack: Editor.STATE.CMDSTACK
		});
		cmd.name = 'add shape';
		cmd.execute();
		Editor.STATE.ADDSHAPE = undefined;
		$('#canvasAdd').removeClass('canvas');
		Editor.Keys.unbind();
		$('#'+Editor.STATE.ADDDIALOG).jqm({overlay: 40, modal: true}).jqmShow();
	},
	updateResource: function () {
		var shape = Editor.STATE.SHAPETOUPDATE;
		var newName = $('#name').val();
		var newNamespacePrefix = $('#namespacePrefix').val();
		var newNamespaceUri = $('#namespaceUri').val();
		if (Editor.STATE.ISADDSHAPE) {
			shape.setName(newName);
			shape.getNamespace().setPrefix(newNamespacePrefix);
			shape.getNamespace().setUri(newNamespaceUri);
			shape.updateText();
			Editor.STATE.ISADDSHAPE = false;
			if (shape.getTypeClass() == 'property') {
				var nW = -shape.getWidth()/2;
				var nH = -shape.getHeight()/2;
				if (Editor.CONFIG.GRID_SNAP) {
					nW = Math.round(nW / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
					nH = Math.round(nH / Editor.CONFIG.GRID_SIZE) * Editor.CONFIG.GRID_SIZE;
				}
				shape.translate(nW,nH);
				shape.drawLines();
			}
		} else {
			var oldName = shape.getName();
			var oldNamespacePrefix = shape.getNamespace().getPrefix();
			var oldNamespaceUri = shape.getNamespace().getUri();
			var oldWidth = shape.getWidth();
			var cmd = new JS.Command({
				execute: function () {
					shape.setName(newName);
					shape.getNamespace().setPrefix(newNamespacePrefix);
					shape.getNamespace().setUri(newNamespaceUri);
					shape.updateText();
				},
				undo: function () {
					shape.setName(oldName);
					shape.getNamespace().setPrefix(oldNamespacePrefix);
					shape.getNamespace().setUri(oldNamespaceUri);
					shape.updateText();
					shape._resize(oldWidth - shape.getWidth(),0);
				},
				stack: Editor.STATE.CMDSTACK
			});
			cmd.name = 'update resource';
			cmd.execute();
		}
		Editor.Keys.bind();
		$('#dialogAddResource').jqmHide();
	},
	cancelUpdateResource: function () {
		if (Editor.STATE.ISADDSHAPE) {
			// tricky
		  Editor.Util.undo();
			Editor.STATE.ISADDSHAPE = false;
		}
		Editor.Keys.bind();
		$('#dialogAddResource').jqmHide();
	},
	updateLiteral: function () {
		var shape = Editor.STATE.SHAPETOUPDATE;
		var newText = $('#text').val();
		var newLang = $('#lang').val();
		var newDatatype = $('#datatype').val();
		if (Editor.STATE.ISADDSHAPE) {
			shape.setText(newText);
			shape.setLang(newLang);
			shape.setDatatype(newDatatype);
			shape.updateText();
			Editor.STATE.ISADDSHAPE = false;
		} else {
			var oldText = shape.getText();
			var oldLang = shape.getLang();
			var oldDatatype = shape.getDatatype();
			var oldWidth = shape.getWidth();
			var oldHeight = shape.getHeight();
			var cmd = new JS.Command({
				execute: function () {
					shape.setText(newText);
					shape.setLang(newLang);
					shape.setDatatype(newDatatype);
					shape.updateText();
				},
				undo: function () {
					shape.setText(oldText);
					shape.setLang(oldLang);
					shape.setDatatype(oldDatatype);
					shape.updateText();
					shape._resize(oldWidth - shape.getWidth(),oldHeight - shape.getHeight());
				},
				stack: Editor.STATE.CMDSTACK
			});
			cmd.name = 'update literal';
			cmd.execute();
		}
		Editor.Keys.bind();
		$('#dialogAddLiteral').jqmHide();
	},
	cancelUpdateLiteral: function () {
		if (Editor.STATE.ISADDSHAPE) {
			// tricky
		  Editor.Util.undo();
			Editor.STATE.ISADDSHAPE = false;
		}
		Editor.Keys.bind();
		$('#dialogAddLiteral').jqmHide();
	},
	moveShapes: function (dir) {
		var step = 1;
		var dx = 0;
		var dy = 0;
		if (Editor.CONFIG.GRID_SNAP) {
			step = Editor.CONFIG.GRID_SIZE;
		}
		switch(dir) {
			case 'left':
				dx = step * -1;
				break;
			case 'right':
				dx = step;
				break;
			case 'up':
				dy = step * -1;
				break;
			case 'down':
				dy = step;
				break;
		}
		var arrSelected = Editor.STATE.SELECTED;
		var arr = new Array();
		for(var i=0;i<arrSelected.length;i++) {
			arr.push(arrSelected[i]);
		}
		var cmd = new JS.Command({
			execute: function () {
				for(var i=0;i<arr.length;i++) {
					arr[i].translate(dx,dy);
					if (arr[i].getTypeClass() == 'property') {
						arr[i].drawLines();
					} else if (arr[i].getTypeClass() == "resource" || arr[i].getTypeClass() == "literal") {
						arr[i].updateLines();
					}
				}
			},
			undo: function () {
				for(var i=0;i<arr.length;i++) {
					arr[i].translate(dx*-1,dy*-1);
					if (arr[i].getTypeClass() == 'property') {
						arr[i].drawLines();
					} else if (arr[i].getTypeClass() == "resource" || arr[i].getTypeClass() == "literal") {
						arr[i].updateLines();
					}
				}
			},
			stack: Editor.STATE.CMDSTACK
		});
		cmd.name = 'move shapes';
		cmd.execute();
	},
	removeShapes: function () {
		var arrSelected = Editor.STATE.SELECTED;
		var arr = new Array();
		for(var i=0;i<arrSelected.length;i++) {
			arr.push(arrSelected[i]);
		}
		var arrProperties = new Array();
		for(var i=0;i<arrSelected.length;i++) {
			var s = arrSelected[i];
			if (s.getTypeClass() == "resource" || s.getTypeClass() == "literal") {
				var aProps = s.getInProperties();
				for(var j=0;j<aProps.length;j++) {
					var p = Editor.STATE.SHAPES.get(aProps[j]);
					if (!p.isDeleted()) {
						arrProperties.push(aProps[j]);
					}
				}
			}
		}
		var cmd = new JS.Command({
			execute: function () {
				for(var i=0;i<arr.length;i++) {
					arr[i]._remove()
				}
				for(var j=0;j<arrProperties.length;j++) {
					var p = Editor.STATE.SHAPES.get(arrProperties[j]);
					if(!p.isDeleted()) {
						p._remove();
					}
				}
			},
			undo: function () {
				for(var i=0;i<arr.length;i++) {
					arr[i].draw();
				}
				for(var j=0;j<arrProperties.length;j++) {
					var p = Editor.STATE.SHAPES.get(arrProperties[j]);
					if(p.isDeleted()) {
						p.draw();
					}
				}
			},
			stack: Editor.STATE.CMDSTACK
		});
		cmd.name = 'remove shapes';
		cmd.execute();
	},
	addObject: function(obj) {
		var s;
		var dx = 0;
		var dy = 0;
		var bbox;
		if (obj.type == 'resource') {
			bbox = obj.resource.shape.bbox;
			s = Editor.Util.addResource(bbox.x,bbox.y,obj.resource.shape.uuid);
		} else if (obj.type == 'literal') {
			bbox = obj.shape.bbox;
			s = Editor.Util.addLiteral(bbox.x,bbox.y,obj.shape.uuid);
			s.setText(obj.text);
			if (obj.lang) {s.setLang(obj.lang)};
			if (obj.datatype) {s.setDatatype(obj.datatype)};
		} else if (obj.type == 'property') {
			bbox = obj.resource.shape.bbox;
			s = Editor.Util.addProperty(bbox.x,bbox.y,obj.resource.shape.uuid,obj.uuidIni,obj.uuidEnd);
		}
		if (obj.type == 'resource' || obj.type == 'property') {	
			var ele = obj.resource.element;
			s.setName(ele.name);
			var ns = ele.namespace;
			if (ns) {
				if (ns.prefix) {s.getNamespace().setPrefix(ns.prefix)}
				if (ns.uri) {s.getNamespace().setUri(ns.uri)}
			}
		}
		s.updateText();
		if (bbox.width) { dx = bbox.width-s.getWidth() }
		if (bbox.height) { dy = bbox.height-s.getHeight() }
		s._resize(dx,dy);
	},
	hideAllLines: function() {
		Editor.STATE.SHAPES.forEach(function(pair) {
			if (!pair.value.isDeleted()) {
				var shape = pair.value;
				if (shape.getTypeClass() == 'property') {
					shape.hideLines();
				}
			}
		});
	},
	showAllLines: function() {
		Editor.STATE.SHAPES.forEach(function(pair) {
			if (!pair.value.isDeleted()) {
				var shape = pair.value;
				if (shape.getTypeClass() == 'property') {
					shape.showLines();
				}
			}
		});
	},
	drawObjects: function (arrObjects) {
		for(i=0;i<arrObjects.length;i++) {
			obj = arrObjects[i];
			if (obj.type != 'property') {
				Editor.Util.addObject(obj);
			}
		}
		for(i=0;i<arrObjects.length;i++) {
			obj = arrObjects[i];
			if (obj.type == 'property') {
				Editor.Util.addObject(obj);
			}
		}
	},
	prepareOptions: function () {
		Editor.Keys.unbind();
		$('#dialogOptions').jqm({overlay: 40, modal: true}).jqmShow();
		$('#gridSize').val(Editor.CONFIG.GRID_SIZE);
		$('#canvasWidth').val(Editor.CONFIG.CANVAS_WIDTH);
		$('#canvasHeight').val(Editor.CONFIG.CANVAS_HEIGHT);
		if (Editor.CONFIG.GRID_SHOW) {
			$('#gridShowYes').attr('checked', true);
			$('#gridShowNo').attr('checked', false);
		} else {
			$('#gridShowYes').attr('checked', false);
			$('#gridShowNo').attr('checked', true);
		}
		if (Editor.CONFIG.GRID_SNAP) {
			$('#gridSnapYes').attr('checked', true);
			$('#gridSnapNo').attr('checked', false);
		} else {
			$('#gridSnapYes').attr('checked', false);
			$('#gridSnapNo').attr('checked', true);
		}

	},
	updateOptions: function () {
		Editor.CONFIG.GRID_SIZE = parseInt($('#gridSize').val());
		Editor.CONFIG.CANVAS_WIDTH = $('#canvasWidth').val();
		Editor.CONFIG.CANVAS_HEIGHT = $('#canvasHeight').val();
		Editor.STATE.CANVAS.setSize(Editor.CONFIG.CANVAS_WIDTH,Editor.CONFIG.CANVAS_HEIGHT);
		Editor.STATE.BACKGROUND0.attr({width: Editor.CONFIG.CANVAS_WIDTH, height:Editor.CONFIG.CANVAS_HEIGHT});
		Editor.STATE.BACKGROUND.attr({width: Editor.CONFIG.CANVAS_WIDTH, height:Editor.CONFIG.CANVAS_HEIGHT});
		$('#dialogOptions').jqmHide();
		Editor.Keys.bind();
	},
	closeOptions: function () {
		$('#dialogOptions').jqmHide();
		Editor.Keys.bind();
	},
	// http://www.netlobo.com/url_query_string_javascript.html
	gup: function (name) {
		name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
		var regexS = "[\\?&]"+name+"=([^&#]*)";
		var regex = new RegExp( regexS );
		var results = regex.exec( window.location.href );
		if( results == null )
			return "";
		else
			return results[1];
	},

	about: function () {
		$('#dialogAbout-'+Editor.STATE.LANG.code).jqm().jqmShow();
	},
	closeAbout: function () {
		$('#dialogAbout-'+Editor.STATE.LANG.code).jqmHide();
	},
	//do the same thing as the Perl "keys" subroutine
	getKeys: function (o) {
		var accumulator = [];
		for (var propertyName in o) {
			accumulator.push(propertyName);
		}
		return accumulator;
	},
	//get values instead of keys
	getValues: function (o) {
		var accumulator = [];
		for (var propertyName in o) {
			accumulator.push(o[propertyName]);
		}
    return accumulator;
	},
}
